package cn.ycc1;

import java.util.Arrays;

/**
 * 自定义动态数组
 * @author ycc
 * @date 2024/6/6
 * 数据存放于数组中，可以自动扩容
 * 定义变量，用于记录数组中实际存储的元素个数
 * 添加元素时，检查容量是否足够，不够时扩容
 * 删除元素时，将指定位置后面的元素向前移动
 * 获取元素时检查是否越界
 * 存储，大小，索引，扩容，越界，移动
 */
public class MyArrayList<E> {
    /**
     * 定义一个私有数组,用来存储数据
     */
    private Object[] elementData;
    /**
     * 定义一个变量，用于记录数组中实际存储的元素个数
     */
    private int size;

    /**
     * 初始化数组大小为10
     */
    public MyArrayList() {
        this(10);
    }

    /**
     * 实现构造方法，初始化数组和元素个数
     * @param initialCapacity
     */
    public MyArrayList(int initialCapacity) {
        if (initialCapacity < 0) {
            throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
        }
        this.elementData = new Object[initialCapacity];
    }

    /**
     * 添加元素
     * @param e
     * @return
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);
        elementData[size++] = e;
        return true;
    }

    /**
     * 获取指定位置元素
     * @param index
     * @return
     */
    public E get(int index) {
        rangeCheck(index);
        return (E) elementData[index];
    }

    /**
     * 数组越界检查,删除指定位置元素
     * @param index
     * @return
     */
    public E remove(int index) {
        rangeCheck(index);
        E oldValue = (E) elementData[index];
        int numMoved = size - index - 1;
        if (numMoved > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, numMoved); // 移动元素
        }
        elementData[--size] = null;
        return oldValue;
    }

    /**
     * 获取数组大小
     * @return
     */
    public int size() {
        return size;
    }

    /**
     * 判断是否为空
     * @return
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 清除所有元素
     */
    public void clear() {
        for (int i = 0; i < size; ++i) {
            elementData[i] = null;
        }
        size = 0;
    }

    /**
     * 扩容
     * @param minCapacity
     */
    private void ensureCapacityInternal(int minCapacity) {
        if (minCapacity - elementData.length > 0) {
            grow(minCapacity);
        }
    }

    /**
     * 扩容
     * @param minCapacity
     */
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    /**
     * 判断是否越界
     * @param index
     */
    private void rangeCheck(int index) {
        if (index >= size || index < 0) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
    }
}
